package com.hk.core.redis.bloomfilter;

import com.hk.commons.util.Lazy;
import com.hk.commons.util.SpringContextHolder;
import com.hk.core.redis.scripting.RedisScriptSource;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import reactor.core.publisher.Mono;

import java.util.Arrays;

/**
 * ReactiveBloomFilter 操作
 * <p>
 * bloomFilter 需要 插件支持 <a href="https://github.com/RedisBloom/RedisBloom"></a>
 *
 * @author Kevin
 * @date 2022-08-27 23:07:52
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class ReactiveBloomFilterOperations {

    private static final DefaultRedisScript<Boolean> BLOOM_ADD_LUA_SCRIPT;

    private static final DefaultRedisScript<Boolean> BLOOM_EXIST_LUA_SCRIPT;

    private static final Lazy<ReactiveStringRedisTemplate> stringRedisTemplate =
            Lazy.of(() -> SpringContextHolder.getBean(ReactiveStringRedisTemplate.class));

    static {
        BLOOM_ADD_LUA_SCRIPT = new DefaultRedisScript<>();
        BLOOM_ADD_LUA_SCRIPT.setScriptSource(RedisScriptSource.BLOOM_FILTER_ADD);
        BLOOM_ADD_LUA_SCRIPT.setResultType(Boolean.class);

        BLOOM_EXIST_LUA_SCRIPT = new DefaultRedisScript<>();
        BLOOM_EXIST_LUA_SCRIPT.setScriptSource(RedisScriptSource.BLOOM_FILTER_EXISTS);
        BLOOM_EXIST_LUA_SCRIPT.setResultType(Boolean.class);
    }

    /**
     * 将值添加到bloom中
     *
     * @param name  bloom名称
     * @param value bloom值
     */
    public static Mono<Boolean> add(String name, String value) {
        return stringRedisTemplate.get().execute(BLOOM_ADD_LUA_SCRIPT, Arrays.asList(name, value))
                .elementAt(0);
    }

    /**
     * 检查bloom中是否存在指定的值
     *
     * @param name  bloom 名称
     * @param value bloom值
     * @return 存在返回 true,不存在返回false
     */
    public static Mono<Boolean> exists(String name, String value) {
        return stringRedisTemplate.get().execute(BLOOM_EXIST_LUA_SCRIPT, Arrays.asList(name, value))
                .elementAt(0);
    }
}
